(function($, doc){
    /**
     * 网页关键词高亮器基类.
     */    
    function _Highlighter(){}
    /**     
     * 参数说明:
     * @context: 对象, 要进行高亮显示的对象.
     * @keys: 字符串, 要进行高亮的词或多个词, 使用 竖杠(|)分隔多个词 .
     */
    _Highlighter.prototype.mark = function(keys, context){};
    /**
     * 清除已经存在的高亮标识.
     */
    _Highlighter.prototype.clearMarks = function(context){
        context = context || doc;
        var marks = context.querySelectorAll('.highlight');
        for(var i=0,marksLen=marks.length; i<marksLen; i++){
            marks[i].parentNode.replaceChild(
                doc.createTextNode(marks[i].innerText), 
                marks[i]
            );            
        }
    },
    /**
     * 获取指定区域的mark信息.
     */
    _Highlighter.prototype.getMarks = function(context){
        context = context || doc;
        var marks = context.querySelectorAll('.highlight');
        var marksMeta = [];
        for(var i=0,marksLen=marks.length; i<marksLen; i++){
            var mark = marks[i],
                markPos = $(mark).getPosition();  
                
            marksMeta.push({
                id : mark.id,
                top : markPos.top,
                left : markPos.left                
            });         
        }   
        return this.sortMarksMeta( marksMeta );
    },
    /**
     * 将mark elements按位置升序排列.
     */
    _Highlighter.prototype.sortMarksMeta = function(marksMeta){        
        if(marksMeta && marksMeta.length){            
            for(var i = 0, iLen = marksMeta.length; i < iLen - 1; i++){
                for(var j = i + 1; j < iLen; j++){
                    
                    var markElementA = marksMeta[i][0] || marksMeta[i];
                    var markElementB = marksMeta[j][0] || marksMeta[j];
                    var flag = false;
                    
                    if( parseInt( markElementA.top ) > parseInt( markElementB.top ) ){
                        flag = true;
                    } 
                    else if( parseInt( markElementA.top ) === parseInt( markElementB.top ) ){
                        if( parseInt( markElementA.left ) > parseInt( markElementB.left ) ){
                            flag = true;
                        }
                    }
                    
                    if( flag ){
                        var temp = marksMeta[j];
                        marksMeta[j] = marksMeta[i];
                        marksMeta[i] = temp;
                    }
                }
            }
        }
        return marksMeta;
    };    
    ujs.define('Highlighter', 'ujs.ui', function(){
        return _Highlighter;
    });
})($, document);

//------------------------------------------------------------------------------------------------------------------------

(function($, doc){
    /**
     * 普通高亮器, 不跨词高亮.
     * 基于 javascript HTML DOM高亮页面特定字词.
     */
    var _highlighterCore = function(context){
        for(var i = 0, childCount = context.childNodes.length; i < childCount; i++) {
            var childNode = context.childNodes[i];
            //Element Node. 
            if(childNode.nodeType == 1) {
                _highlighterCore.call(this, childNode);
            } 
            //Text Node.
            else if (childNode.nodeType == 3) {
                if( !(context.nodeName == 'A') && childNode.data.search(this.keyRegex) != -1 ) {
                    
                    var highlighterWrapperTemp = doc.createElement('div');
                    highlighterWrapperTemp.innerHTML = childNode.data.replace(
                        this.keyRegex, 
                        function(matchStr){
                            var keyGuid = String.newGuid('highlight_');
                            return '<a id="{guid}" href="#{guid}" class="highlight" >{matchStr}</a>'.format({
                                guid : keyGuid,
                                matchStr : matchStr
                            });    
                        }
                    );
                    
                    var highlighterFragmentTemp = doc.createDocumentFragment();
                    for(var j=0, jLen = highlighterWrapperTemp.childNodes.length; j<jLen; j++){
                        highlighterFragmentTemp.appendChild( highlighterWrapperTemp.childNodes[0] );
                    }    
                                
                    context.replaceChild(highlighterFragmentTemp, childNode);                
                }
            }
        }
    };
    
    var _CommonHighlighter = function (){        
    }.extend(ujs.ui.Highlighter);
        
    _CommonHighlighter.prototype.mark = function(keys, context){    
        this.clearMarks(context);
        this.keys = keys.replace(/\s+/gi,'|');            
        this.keyRegex = new RegExp('(' + this.keys + ')', 'gi');
        _highlighterCore.call(this, context);
    };
        
    ujs.define('CommonHighlighter', 'ujs.ui', function(){
        return _CommonHighlighter;
    });
    
})($, document);

//------------------------------------------------------------------------------------------------------------------------

(function($, doc){
    /**
     * 跨词高亮器.
     */
    var _CrossElementsHighlighter = function (){        
    }.extend(ujs.ui.Highlighter);
    
    ujs.define('CrossElementsHighlighter', 'ujs.ui', function(){
        return _CrossElementsHighlighter;
    });
})($, document);